# -*- coding:UTF-8 -*-
import os
from core.file import File
from config.config import config
from infrastructure.constant.str_content_constant import StrContentConstant
from infrastructure.rules.form_rule import FormRule
from infrastructure.rules.validators.multi_validator import MultiValidator
from infrastructure.rules.validators.str_validator import StrContentValidator, StrLengthValidator
from infrastructure.utils.request_util import get, post, put, delete
from infrastructure.utils.base64_util import encode_from_file, decode_2_file
from infrastructure.utils.file_util import make_file
from infrastructure.utils.dateutils import get_date_from_dateStr


class GiteeFile(File):
    name = "gitee"
    # ["access_token", "owner", "repo", "branch"]
    setup_items = {
        "access_token": FormRule(name="access_token", label="用户授权码", required=True, validator=MultiValidator(
            validators=[StrLengthValidator(length=32), StrContentValidator(white_chars=f"{StrContentConstant.LETTER_LOWER}{StrContentConstant.LETTER_UPPER}{StrContentConstant.NUMBER}")])),
        "owner": FormRule(name="owner", label="仓库所属空间地址", required=True, validator=MultiValidator(validators=[StrContentValidator(white_chars=f"{StrContentConstant.LETTER_LOWER}{StrContentConstant.LETTER_UPPER}{StrContentConstant.NUMBER}_-")])),
        "repo": FormRule(name="repo", label="仓库路径", required=True, validator=MultiValidator(validators=[StrContentValidator(white_chars=f"{StrContentConstant.LETTER_LOWER}{StrContentConstant.LETTER_UPPER}{StrContentConstant.NUMBER}_-")])),
        "branch": FormRule(name="branch", label="仓库路径", required=True, validator=MultiValidator(validators=[StrContentValidator(white_chars=f"{StrContentConstant.LETTER_LOWER}{StrContentConstant.LETTER_UPPER}{StrContentConstant.NUMBER}\_\-\/")])),
    }

    def __init__(self, relative_path, base, is_on_remote=True, is_on_local=False, size=0, is_folder=True, sha:str="local_sha", remote_time=None, parent=None):
        """
        Gitee访问
        :param sha:可以是分支名(如master)、Commit或者目录Tree的SHA值
        """
        super(GiteeFile, self).__init__(relative_path, base, is_on_remote=is_on_remote, is_on_local=is_on_local, size=size, is_folder=is_folder, remote_time=remote_time, parent=parent)
        self.access_token = config.get(self.__class__.name, "access_token")
        self.owner = config.get(self.__class__.name, "owner")
        self.repo = config.get(self.__class__.name, "repo")
        self.branch = config.get(self.__class__.name, "branch")
        self.sha = sha if sha else self.branch
        if not sha or sha == self.branch and self.is_on_remote:
            self.__start()

    def __start(self):
        tree = self.__get_file_list()
        if tree and len(tree) > 0:
            for item in tree:
                self.add_child(GiteeFile(relative_path=f"{self.relative_path}/{item['path']}", base=self.base, is_on_remote=True, is_on_local=True is os.path.exists(f"{self.base}/{item['path']}"), size=item["size"], is_folder=False if item["type"] == "blob" else True, sha=item["sha"]))
        self.add_files()

    def __get_file_list(self, recursive=1):
        """
        获取目录Tree
        REF:https://gitee.com/api/v5/swagger#/getV5ReposOwnerRepoGitTreesSha
        :param recursive:
        :return:赋值为1递归获取目录
        """
        url = str(config.get(self.__class__.name, "tree")).format(self.owner, self.repo, self.sha)
        params = {
            "access_token": config.get(self.__class__.name, "access_token"),
            "recursive": recursive
        }
        results = get(url, data=params)
        if results and results.get("tree", None):
            return results["tree"]
        else:
            return None

    def download__(self):
        """
        获取文件Blob
        REF:https://gitee.com/api/v5/swagger#/getV5ReposOwnerRepoGitBlobsSha
        :param path: 文件路径, 相对路径
        :param sha: 文件的 Blob SHA，可通过 [获取仓库具体路径下的内容] API 获取
        :return:
        """
        url = str(config.get(self.__class__.name, "download_file")).format(self.owner, self.repo, self.sha)
        params = {
            "access_token": self.access_token
        }
        results = get(url, data=params)
        if results and len(results) > 0:
            if results["size"] == 0:
                make_file(os.path.join(self.base, self.relative_path))
            else:
                decode_2_file(results["content"], os.path.join(self.base, self.relative_path))
            self.is_on_local = True
            return True
        return False

    def update__(self):
        """
        上传文件
        REF:https://gitee.com/api/v5/swagger#/putV5ReposOwnerRepoContentsPath
        :param path: 文件路径, 相对路径
        :return:
        """
        file_path = os.path.join(self.base, self.relative_path)
        if os.stat(file_path).st_size == 0:
            return None
        url = str(config.get(self.__class__.name, "update_file")).format(self.owner, self.repo, self.relative_path)
        params = {
            "access_token": self.access_token,
            "content": encode_from_file(file_path),
            "sha": self.sha,
            "message": f"更新文件{self.relative_path}",
            "branch": self.branch
        }
        results = put(url, data=params)
        return results

    def add__(self):
        """
        在远程新建文件，需要在现在本地创建文件，并书写文件内容后才可以在远程新建
        REF:https://gitee.com/api/v5/swagger#/postV5ReposOwnerRepoContentsPath
        :param path: 文件路径, 相对路径
        :return:
        """
        file_path = os.path.join(self.base, self.relative_path)
        if os.stat(file_path).st_size == 0:
            return None
        url = str(config.get(self.__class__.name, "add_file")).format(self.owner, self.repo, self.relative_path)
        params = {
            "access_token": self.access_token,
            "content": encode_from_file(file_path),
            "message": f"新增文件{self.relative_path}",
            "branch": self.branch
        }
        results = post(url, data=params)
        self.is_on_remote = True
        return results

    def delete__(self):
        """
        删除远程文件
        REF:https://gitee.com/api/v5/swagger#/deleteV5ReposOwnerRepoContentsPath
        :param path: 文件路径, 相对路径
        :return:
        """
        url = str(config.get(self.__class__.name, "delete_file")).format(self.owner, self.repo, self.relative_path)
        params = {
            "access_token": self.access_token,
            "sha": self.sha,
            "message": f"删除文件{self.relative_path}",
            "branch": self.branch
        }
        results = delete(url, data=params)
        self.is_on_remote = False
        return results

    def get_commits(self, contain_file=True, page=1, per_page=1):
        """
        仓库的所有提交
        REF:https://gitee.com/api/v5/swagger#/getV5ReposOwnerRepoCommits
        :param contain_file: 是否包含当前文件
        :param page: 当前的页码
        :param per_page: 每页的数量，最大为 100
        :return:
        """
        url = str(config.get(self.__class__.name, "get_commits")).format(self.owner, self.repo)
        params = {
            "access_token": config.get(self.__class__.name, "access_token"),
            "path": self.relative_path if contain_file else "",
            "page": page,
            "per_page": per_page
        }
        results = get(url, data=params)
        return results

    def update_remote_time__(self):
        """
        更新远程最新提交时间
        :return:
        """
        results = self.get_commits(contain_file=True)
        if results and len(results) > 0:
            self.remote_time = get_date_from_dateStr(results[0]["commit"]["committer"]['date'])

    def refresh(self):
        self.access_token = config.get(self.__class__.name, "access_token")
        self.owner = config.get(self.__class__.name, "owner")
        self.repo = config.get(self.__class__.name, "repo")
        self.branch = config.get(self.__class__.name, "branch")
        self.children = dict()
        self.__start()

    def __hash__(self):
        return hash(self.__class__.name)


if __name__ == '__main__':
    gitee = GiteeFile(sha="master", relative_path="", base="C:\\Users\\田芷瑜\\Documents\\docs", is_folder=True)